//
//  BBOverlayView.m
//  xNose
//
//  Created by ben smith on 12/09/08.
//  Copyright 2008 __MyCompanyName__. All rights reserved.
//

#import "BBOverlayView.h"
#import "BBNode.h"
#import "BBNodeView.h"
#import "BBNodeController.h"
#import "BBControllerNodeView.h"
#import "BBNodeViewFactory.h"
#import "BBViewThumbnailer.h"
#import "BBContainerInfoNodeView.h"
#import "BBDefaultController.h"


@implementation BBOverlayView

@synthesize transitionView;

- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
			dim = NO;
			drawConnections = NO;
			[self activate];
			[self setupTextAttributes];
			logo = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"masthead" ofType:@"png"]];
	  }
    return self;
}



// shuts off all the notifications
-(void)deactivate
{
	[[NSNotificationCenter defaultCenter] removeObserver:self];
}

// turn on all my notifications
-(void)activate
{
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(openController:) name:@"BBOpenControllerNotification" object:nil];
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(closeController:) name:@"BBCloseControllerNotification" object:nil];
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showConnectedNotification:) name:@"BBShowConnected" object:nil];
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(toggleConnectedNotification:) name:@"BBToggleConnected" object:nil];
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(highlightConnectedNotification:) name:@"BBHighlightConnected" object:nil];

	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(openInfo:) name:@"BBOpenInfoNotification" object:nil];
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(closeInfo:) name:@"BBCloseInfoNotification" object:nil];
}


-(void)showConnectedNotification:(id)sender
{
	drawConnections = YES;
	[self setNeedsDisplay:YES];	
}

-(void)toggleConnectedNotification:(id)sender
{
	drawConnections = !drawConnections;
	[self setNeedsDisplay:YES];
}

-(void)highlightConnectedNotification:(id)sender
{
	drawImages = !drawImages;
	if (dim) {
		[[BBNodeController sharedNodeController] removeDimLayer];
		dim = NO;
		drawConnections = drawStateSave;
	} else {
		drawStateSave = drawConnections;
		drawConnections = YES;
		[[BBNodeController sharedNodeController] addDimLayer:YES];
		[self shuffleConnectedViews];
		dim = YES;		
	}
	[self setNeedsDisplay:YES];
}


- (void)drawRect:(NSRect)rect {
    // Drawing code here.	
//	[[NSColor redColor] set];
//	[NSBezierPath strokeRect:NSInsetRect([self bounds], 30, 30)];
//	[NSBezierPath strokeRect:sourceFrame];
//	[NSBezierPath strokeRect:[transitionView frame]];
	[self drawConnected];
//	if (drawConnections && ![[BBNodeController sharedNodeController] isActive]) [self drawConnected];
	NSString * title = [[[BBNodeController sharedNodeController] rootNode] title];
	NSSize titlesize = [title sizeWithAttributes:textAttributes];
//	[[NSColor whiteColor] set];
//	[roundRect stroke];
//	[[NSColor colorWithDeviceWhite:0.1 alpha:0.4] set];
//	[roundRect fill];
	
	
	// just a bit of debugging code
//	[[NSColor yellowColor] set];
//	BBNode * root = [[BBNodeController sharedNodeController] rootNode];
//	for (BBNode * kid in root.children) {
//		[self drawNodeFrame:kid];
//	}
	NSSize imageSize = [logo size];
	NSPoint drawPoint = NSMakePoint(NSMidX([self bounds]) - (imageSize.width/2.0), NSMaxY([self bounds]) - imageSize.height - 20);
	[logo drawInRect:NSMakeRect(drawPoint.x,drawPoint.y, imageSize.width, imageSize.height)
					fromRect:NSZeroRect 
				 operation:NSCompositeSourceOver 
					fraction:1.0];


	textRect =  NSMakeRect(NSMidX(self.bounds) - (titlesize.width/2.0),   NSMaxY(self.bounds) - (titlesize.height) - 40, titlesize.width, titlesize.height);
	[title drawInRect:textRect withAttributes:textAttributes];


}

-(void)drawNodeFrame:(BBNode*)aNode
{
	[NSBezierPath strokeRect:[aNode.view frame]];
	return;
	for (BBNode * kid in aNode.children) {
		[self drawNodeFrame:kid];
	}
}


-(void)shuffleConnectedViews
{
	NSView * dimView = [[BBNodeController sharedNodeController] dimmingView];
	// move the views from the underlay to the dimming view
	[self findConnectedNodesIn:[[BBNodeController sharedNodeController] rootNode]];
	for (BBNode* start in connectedNodes) {
		[start.view removeFromSuperview];
		[dimView addSubview:start.view];
		for (BBNode* end in start.connections) {
			[end.view removeFromSuperview];
			[dimView addSubview:end.view];
		}
	}
}

- (void)setupTextAttributes
{
	NSFont * thisFont = [BBDefaultController titleFont];
	float height = [BBDefaultController fontHeight:thisFont];
	textRect =  NSMakeRect(NSMidX(self.bounds) - (NSWidth(self.bounds)/4.0),   NSMaxY(self.bounds) - (height) - 10, NSWidth(self.bounds)/2.0, height);
	
	NSMutableParagraphStyle * style = [[NSMutableParagraphStyle alloc] init];
	[style setParagraphStyle:[NSParagraphStyle defaultParagraphStyle]];
	[style setAlignment:NSCenterTextAlignment];
	
	textAttributes = [[NSDictionary dictionaryWithObjectsAndKeys:thisFont,NSFontAttributeName,[NSColor whiteColor],NSForegroundColorAttributeName,style,NSParagraphStyleAttributeName,nil] retain];
	[style release];	
}

-(void)drawConnected
{
	if (connectedNodes == nil) connectedNodes = [[NSMutableArray alloc] init];
	[connectedNodes removeAllObjects];
	
	[self findConnectedNodesIn:[[BBNodeController sharedNodeController] rootNode]];
	
	if (curves == nil) curves = [[NSMutableArray alloc] init];
	[curves removeAllObjects];
	if (dots == nil) dots = [[NSMutableArray alloc] init];
	[dots removeAllObjects];
	if (circles == nil) circles = [[NSMutableArray alloc] init];
	[circles removeAllObjects];
	
	// now go through the connected nodes and draw the conenctions
	for (BBNode* start in connectedNodes) {
		for (BBNode* end in start.connections) {
			[self drawConnectionBetween:start and:end];			
		}
	}
	[[NSColor yellowColor] set];
	if (drawConnections && ![[BBNodeController sharedNodeController] isActive])
		[curves makeObjectsPerformSelector:@selector(stroke)];
	[circles makeObjectsPerformSelector:@selector(stroke)];
	[dots makeObjectsPerformSelector:@selector(fill)];		
}


-(void)findConnectedNodesIn:(BBNode*)aNode
{
	if ((![aNode hasChildren]) && ([aNode.connections count] > 0)) {
		// add it to the array if it isnt already there
		[connectedNodes addObject:aNode];
		return;
	}
	for (BBNode * kid in aNode.children) {
		[self findConnectedNodesIn:kid];
	}
}

-(void)drawConnectionBetween:(BBNode*)aNode and:(BBNode*)bNode
{
	BBNodeView * start = (BBNodeView *)aNode.view;
	BBNodeView * end = (BBNodeView *)bNode.view;
	
	BBNode * fromNode = aNode;
	BBNode * toNode = bNode;
	
	NSRect startRect = [start frame];
	NSRect endRect = [[[self window] contentView] convertRect:[BBNodeViewFactory connectionButtonRectForView:end] fromView:end];

	
	if (NSMidX([start frame]) > NSMidX([end frame])) {
		start = (BBNodeView *)bNode.view;
		end = (BBNodeView *)aNode.view;
		fromNode = bNode;
		toNode = aNode;
		// new start/end;
		startRect = [[[self window] contentView] convertRect:[start bounds] fromView:start];
		endRect = [[[self window] contentView] convertRect:[BBNodeViewFactory connectionButtonRectForView:end] fromView:end];
	}
	
	
	NSPoint c1 = NSMakePoint(NSMaxX(startRect) - 10, NSMidY(startRect) + 4);
	NSPoint c4 = NSMakePoint(NSMinX(endRect) - 2, NSMidY(endRect));
	
	if (!fromNode.parent.isOpen) {
		c1 = NSMakePoint(NSMaxX(startRect) - 5, NSMidY(startRect));
	} 
	if (!toNode.parent.isOpen) {
		endRect = [end frame];
		c4 = NSMakePoint(NSMinX(endRect) + 10, NSMidY(endRect));
	}
	
	NSPoint c2 = c1;
	NSPoint c3 = c4;
	
	c2.x = c1.x + (c4.x - c1.x)/2.0;
	c3.x = c2.x;// + (c4.x - c1.x)/2.0;
	
	NSBezierPath * curve = [NSBezierPath bezierPath];
	float array[2];
	array[0] = 5.0; //segment painted with stroke color
	array[1] = 2.0; //segment not painted with a color
	
	[curve setLineDash: array count: 2 phase: 0.0];
	[curve setLineWidth:2.0];
	
	[curve moveToPoint:c1];
	[curve curveToPoint:c4 controlPoint1:c2 controlPoint2:c3];
	
	[curves addObject:curve];
	
	float scale = [[BBNodeController sharedNodeController] scale];
	NSRect ovalRect = NSMakeRect(c1.x - (8*scale), c1.y - (5*scale), (8*scale), (10*scale));

	if (fromNode.parent.isOpen) [dots addObject:[NSBezierPath bezierPathWithOvalInRect:ovalRect]];
	if (toNode.parent.isOpen) {
		NSBezierPath * circle = [NSBezierPath bezierPathWithOvalInRect:NSInsetRect(endRect, -2, -2)];
		[circle setLineDash: array count: 2 phase: 0.0];
		[circle setLineWidth:2.0];
		[circles addObject:circle];
	}
	
	if (drawImages) {
	//	[start removeFromSuperview];
	//	[self addSubview:start];
//		CGFloat scale = [[BBNodeController sharedNodeController] scale];
//		CGFloat ratio = 1.0/scale;
//		[start scaleUnitSquareToSize:NSMakeSize(ratio, ratio)];
//		NSImage * image1 = [BBViewThumbnailer createImageFromView:start];
//		[start scaleUnitSquareToSize:NSMakeSize(scale, scale)];		
//		NSLog(@"frame: %@ bounds %@",NSStringFromRect(start.bounds),NSStringFromSize([image1 size]));
//		[image1 drawInRect:[[[self window] contentView] convertRect:start.bounds fromView:start] fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
//		NSImage * image2 = [BBViewThumbnailer createImageFromView:end];
//		[image2 drawInRect:[[[self window] contentView] convertRect:end.bounds fromView:end] fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];		
	}
	
	
}


-(void)closeController:(NSNotification*)note
{
	[[controller animator] setFrame:controllerStart];
	
	[self performSelector:@selector(undim:) withObject:nil afterDelay:0.45];
}

-(void)undim:(id)sender
{
	[[BBNodeController sharedNodeController] removeDimLayer];
	dim = NO;
	[self setNeedsDisplay:YES];
}

-(void)openController:(NSNotification*)note
{
	if ([[BBNodeController sharedNodeController] isActive]) return;
	
	
	if (![[note object] isKindOfClass:[BBNode class]]) return;
	[[BBNodeController sharedNodeController] releaseEdit:nil];
	
	[[BBNodeController sharedNodeController] addDimLayer:NO];
	dim = YES;
	
	NSPoint mouseDown = [[[self window] contentView] convertPoint:[[self window] mouseLocationOutsideOfEventStream] toView:self];
	
	float height = 300;
	float width = 500;
	
	if ([[note object] hasChildren]) width = 300;
	
	NSRect start = NSMakeRect(mouseDown.x, mouseDown.y, 1, 1);
	
	NSRect end = NSMakeRect(NSMidX(self.bounds) - (width/2.0), NSMidY(self.bounds) - (height/2.0), width, height);
	
	BBControllerNodeView * controlView = [[BBControllerNodeView alloc] initWithFrame:end];
	[controlView setNode:[note object]]; //TODO: make this the right node!!
	[controlView setFrame:start];
	[self addSubview:controlView];
	controller = controlView;
	controllerStart = start;
	[[controlView animator] setFrame:end];
	[self setNeedsDisplay:YES];
}

-(void)openInfo:(NSNotification*)note
{
	if ([[BBNodeController sharedNodeController] isActive]) return;
	
	drawStateSave = drawConnections;
	drawConnections = NO;
	[[BBNodeController sharedNodeController] addDimLayer:NO];
	dim = YES;		

	[self setNeedsDisplay:YES];
	// open an info window 
	BBNodeView * sourceView = [note object];
	sourceFrame = [sourceView frame];

	NSImage * image = [BBViewThumbnailer createImageFromSubView:[sourceView superview] rect:sourceFrame];
	[sourceView.node hideView]; 
	NSImageView * iView = [[NSImageView alloc] initWithFrame:sourceFrame];
	[iView setImageFrameStyle:NSImageFrameNone];
	[iView setImageScaling:NSScaleToFit];
	[iView setImage:image];
	[self addSubview:iView];
	[[iView animator] setFrame:NSMakeRect(NSMidX(sourceFrame), NSMinY(sourceFrame), 1, NSHeight(sourceFrame))];
	self.transitionView = iView;
	[iView release];
	[self performSelector:@selector(middleOpenInfo:) withObject:sourceView afterDelay:0.4];
	[self setNeedsDisplay:YES];
}

-(void)middleOpenInfo:(BBNodeView*)nodeView
{
	
	float height = [BBNodeViewFactory maxHeightForNode:nodeView.node];
	height += 500;
	if (height > 600) height = 600;
	NSRect newFrame = sourceFrame;
	float expand = height - NSHeight(sourceFrame);
	newFrame.size.height = height;
	newFrame.origin.y -= expand;
	newFrame.size.width = [[NSUserDefaults standardUserDefaults] floatForKey:@"BBContainerWidth"];
	
	newFrame.origin.x = NSMidX(sourceFrame) - (NSWidth(newFrame)/2.0);

	
	[infoView release];
	infoView = [[BBContainerInfoNodeView alloc] initWithFrame:newFrame];
	[infoView setNode:[nodeView node]];
	

	float scale = [[BBNodeController sharedNodeController] scale];
	
	NSRect scaledFrame = newFrame;
	
	scaledFrame.size.height *= scale;	
	if (scaledFrame.size.height > 600) scaledFrame.size.height = 600;

	scaledFrame.size.width *= scale;
	
	scaledFrame.origin.y -= (NSHeight(scaledFrame) - NSHeight(newFrame));
	if (scaledFrame.origin.y < 10) scaledFrame.origin.y = 10;
	
	scaledFrame.origin.x -= (NSWidth(scaledFrame) - NSWidth(newFrame))/2.0;
	
	[infoView setFrame:scaledFrame];
	[infoView scaleUnitSquareToSize:NSMakeSize(scale, scale)];
	[infoView setupInfoView];
	[self addSubview:infoView];
	
	NSImage * image = [BBViewThumbnailer createImageFromSubView:[infoView superview] rect:[infoView frame]];

	[infoView removeFromSuperview];
	
//	NSImage * image = [BBViewThumbnailer createImageFromView:infoView];
	
	NSImageView * iView = [[[NSImageView alloc] initWithFrame:NSMakeRect(NSMidX(scaledFrame), NSMinY(scaledFrame), 1, NSHeight(scaledFrame))] autorelease];
	
	[iView setImageFrameStyle:NSImageFrameNone];
	[iView setImageScaling:NSScaleToFit];
	[iView setImage:image];
	[self addSubview:iView];
	[[iView animator] setFrame:scaledFrame];
	
	[self performSelector:@selector(finishOpenInfo:) withObject:infoView afterDelay:0.5];
	[self performSelector:@selector(trashView:) withObject:iView afterDelay:0.5];
//	[self addSubview:infoView];
//	[[infoView animator] setFrame:sourceFrame];
}

-(void)finishOpenInfo:(BBNodeView*)nodeView
{
	[self addSubview:nodeView];

}

-(void)trashView:(NSView*)aView
{
	[aView removeFromSuperview];
}

-(void)closeInfo:(NSNotification*)note
{
	drawConnections = NO;
	[self setNeedsDisplay:YES];
	// open an info window 
	NSImage * image = [BBViewThumbnailer createImageFromSubView:[infoView superview] rect:[infoView frame]];
	NSImageView * iView = [[NSImageView alloc] initWithFrame:[infoView frame]];
	[iView setImageFrameStyle:NSImageFrameNone];
	[iView setImageScaling:NSScaleToFit];
	[iView setImage:image];
	[self addSubview:iView];
	[infoView removeFromSuperview];
	[[iView animator] setFrame:NSMakeRect(NSMidX([infoView frame]), NSMinY([infoView frame]), 1, NSHeight([infoView frame]))];
	[self performSelector:@selector(trashView:) withObject:iView afterDelay:0.4];
	[self performSelector:@selector(middleCloseInfo:) withObject:infoView afterDelay:0.4];
}

-(void)middleCloseInfo:(BBNodeView*)nodeView
{
	[[transitionView animator] setFrame:sourceFrame];
	[self performSelector:@selector(finalCloseInfo:) withObject:nodeView afterDelay:0.5];	
}

-(void)finalCloseInfo:(BBNodeView*)nodeView
{
	[nodeView.node showView];
	[transitionView removeFromSuperview];
	drawConnections = drawStateSave;
	[self undim:self];
}

- (void) dealloc
{
	[self.transitionView release];
	[[NSNotificationCenter defaultCenter] removeObserver:self];
	[super dealloc];
}



@end
